// Author: 		ngohaibac@hocdelam.org
// Date:		26th Oct, 2009
// Hardware:	TMS320F28335
// Module:		LCD Module	

#include "DSP2833x_System.h"

#include "DSP2833x_LCDLib.h"

#define LCD_CTRL			0 // LCD Control (Command)
#define LCD_DATA			1 // LCD Data

#define LCD_PORT(x)			(EXT_BUS_LCD = x)

// Local functions
void lcd_out(Uint16 data);
void lcd_out2(Uint16 rs, Uint16 data);


//===========================================
// Initialize ADC Module
//===========================================
void LCD_Init(void){
	LCD_PORT(0);   				/* 0x00 out */
	Delay_Ms(15);				/* wait 15ms */

	lcd_out(0x03);				/* function set 1 */
	Delay_Ms(4);
	lcd_out(0x03);				/* function set 2 */
	Delay_Ms(4);
	lcd_out(0x03);				/* function set 3 */
	Delay_Ms(4);
	lcd_out(0x02);				/* function set */
	Delay_Ms(4);

	lcd_out2(LCD_CTRL, 0x28);	/* function set */
	DELAY_US(40);
	lcd_out2(LCD_CTRL, 0x0c);	/* display on : Disp=ON, Cursor=OFF, Cursor_Blink=OFF */
	DELAY_US(40);
	lcd_out2(LCD_CTRL, 0x06);	/* entry mode */
	DELAY_US(40);
	lcd_out2(LCD_CTRL, 0x01);	/* clear display */
	Delay_Ms(2);	
}

//=============================================
// LCD Goto XY: x: column, y: row
//=============================================

void LCD_gotoXY(Uint16 x, Uint16 y){
	Uint16	pos;

	switch(y){
		case 0:	// 1st line
			pos = 0x80 | (x & 0x7f);
			break;
		case 1:	// 2nd line
			pos = 0x80 | ((0x40 + x) & 0x7f);
			break;
		case 2:	// 3rd line
			pos = 0x80 | ((0x14 + x) & 0x7f);
			break;
		case 3:	// 4th line
			pos = 0x80 | ((0x54 + x) & 0x7f);
			break;
		default: break;
	}

	lcd_out2(LCD_CTRL, pos);
	DELAY_US(40);
}     
//=============================================
// LCD Print Char
//=============================================

void LCD_PrChar(Uint16 c){
	lcd_out2(LCD_DATA, c);
	DELAY_US(40);
}
//=============================================
// LCD Print String
//=============================================
void LCD_PrString(char *str){
	while(*str){
		lcd_out2(LCD_DATA, *str++);
		DELAY_US(40);
	};
} 
//=============================================
// LCD Print Hex number into String
//=============================================
void LCD_PrHex(Uint16 hex_data,Uint16 number_of_digit){
	Uint16 buffer[4];
	Hex2Ascii(hex_data,buffer);
	while(number_of_digit--)
		LCD_PrChar(buffer[number_of_digit]);
			
}         

void LCD_PrDec(Uint16 hex_data,Uint16 number_of_digit){
	Uint16 buffer[5];
	Hex2Dec(hex_data,buffer);
	while(number_of_digit--)
		LCD_PrChar(buffer[number_of_digit]);
		
}
//=============================================
// Clear LCD Display at line
//=============================================
void LCD_clear_line(Uint16 line){	/* 0=1st, 1=2nd, 2=3rd, 3=4th line */
	Uint16	len=16;
	LCD_gotoXY(0,line);
	if(line >= 2) len=20;
	
	while(len--){
		lcd_out2(LCD_DATA, ' ');
		DELAY_US(40);
	}
}
//=============================================
// Doing some commands
//=============================================
void LCD_Command(Uint16 command){
	lcd_out2(LCD_CTRL, command);
	DELAY_US(40);
}

//=============================================
// Display data: LCD_OUT, LCD_OUT2
//=============================================
void lcd_out(Uint16 data){
	Uint16 d;

	d = data << 4;
	LCD_PORT(d);		// RS=0, E=0
	LCD_PORT(d | 0x04);	// RS=0, E=1
	DELAY_US(1);

	LCD_PORT(d);		// RS=0, E=0
	DELAY_US(1);
}

void lcd_out2(Uint16 rs, Uint16 data){
	Uint16	 r, d;

	if(rs) r = 0x01;
	else r = 0x00;	
	DELAY_US(1);

	d = (data & 0xf0) | r;	// upper 4 bit
	LCD_PORT(d);		 	// E = 0
	DELAY_US(1);
	LCD_PORT(d | 0x04);		// E = 1
	DELAY_US(1);
	LCD_PORT(d);			// E = 0
	DELAY_US(1);

	d = (data<<4) | r;		// lower 4 bit
	LCD_PORT(d);			// E = 0
	DELAY_US(1);
	LCD_PORT(d | 0x04);		// E = 1
	DELAY_US(1);
	LCD_PORT(d);			// E = 0
	DELAY_US(1);
}   
